package cn.yitun.chat.yitunchatbasesdk.server.im.dispatcher.impl;

import cn.yitun.chat.yitunactiondispatch.extend.ActionRequest;
import cn.yitun.chat.yitunactiondispatch.extend.ActionResponse;
import cn.yitun.chat.yitunactiondispatch.extend.ArgumentBox;
import cn.yitun.chat.yitunactiondispatch.extend.ResultHandler;
import cn.yitun.chat.yituncommonlibutil.lib.YitunJsonUtil;
import cn.yitun.chat.yituncommonmessage.AbstractMessage;
import cn.yitun.chat.yituncommonmessage.Head;
import cn.yitun.chat.yituncommonmessage.Info;
import cn.yitun.chat.yituncommonmessage.result.ResultBodyMessage;
import cn.yitun.chat.yituncommonmessage.result.ResultMessage;
import cn.yitun.chat.yituncommonmessage.server.ServerHead;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Date 2019-01-12 12:05:12<br>
 * Description
 * @author yitun
 * @since 1.1
 */

public class HandlerResultHandler implements ResultHandler {

	@Override
	public Object handle(Object result, ActionRequest request, ActionResponse response, ArgumentBox argumentBox) {

		Object value = null;
		Object requestData = request.getData();
		if (null == result) {
			Head head = getHead(argumentBox, requestData);
			ResultMessage m = new ResultMessage();
			m.setHead(head);
			value = m;
		} else if (result instanceof AbstractMessage) {
			AbstractMessage<?> m = (AbstractMessage<?>) result;
			if (null == m.getHead()) {
				Head head = getHead(argumentBox, requestData);
				m.setHead(head);
			}
			value = m;
		} else if (result instanceof Info) {
			Head head = getHead(argumentBox, requestData);
			ResultBodyMessage m = new ResultBodyMessage();
			m.setHead(head);
			m.setInfo((Info) result);
			value = m;
		} else if (result instanceof Map) {
			Head head = getHead(argumentBox, requestData);
			ResultBodyMessage m = new ResultBodyMessage();
			m.setHead(head);
			m.setBody(result);
			value = m;
		} else if (result instanceof Collection) {
			Map<String, Object> map = new HashMap<>(1);
			map.put("items", result);
			Head head = getHead(argumentBox, requestData);
			ResultBodyMessage m = new ResultBodyMessage();
			m.setHead(head);
			m.setBody(map);
			value = m;
		} else {
			Head head = getHead(argumentBox, requestData);
			ResultBodyMessage m = new ResultBodyMessage();
			m.setHead(head);
			m.setBody(result);
			value = m;
		}
		return value;
	}

	private Head getHead(ArgumentBox argumentBox, Object requestData) {
		ServerHead head = argumentBox.get(ServerHead.class);
		if (null == head) {
			JsonObject jo = argumentBox.get(JsonObject.class);
			if (null != jo) {
				boolean hasHead = jo.has("head");

				if (hasHead) {
					JsonObject headElement = jo.getAsJsonObject("head");
					head = new Gson().fromJson(headElement, ServerHead.class);
				}
			} else {
				String message = (requestData instanceof String) ? requestData.toString() : "";
				if (YitunJsonUtil.mayBeJSON(message)) {
					boolean hasHead = jo.has("head");
					if (hasHead) {
						JsonObject headElement = jo.getAsJsonObject("head");
						head = new Gson().fromJson(headElement, ServerHead.class);
					}
				}
			}
		}
		if (null == head) {
			head = new ServerHead();
		}
		head.setTimestamp(System.currentTimeMillis());
		return head;
	}
}
